#include <list>
#include <vector>
#include <map>
#include <string>
#include <fstream>
#include <algorithm>
#include "../lexer/lexer.h"
#include "../reader/reader.h"

#ifndef __SILK__PARSER__
#define __SILK__PARSER__

struct AST_Node {
    AST_Node* parent;
};

struct ExpressionNode : public AST_Node {
};

struct OperatorExpressionNode : public ExpressionNode {
    ExpressionNode* left;
    std::string middle;
    ExpressionNode* right;
};

struct FunctionExpressionNode : public ExpressionNode {
    std::string function_name;
    ExpressionNode* expression;
};

struct FactorNode : public ExpressionNode {
    std::string value;
};

struct VariableFactorNode : public FactorNode {
    std::string type;
};

struct NumberFactorNode : public FactorNode {
    unsigned long bits;
    bool is_unsigned;
    bool is_float;
};

struct StringFactorNode : public FactorNode {
    unsigned long length;
};

struct StatementNode : public AST_Node {
};

struct ClassStatementNode : public StatementNode {
    std::list<ClassStatementNode*> parents;
    std::string name;
    std::list<StatementNode*> public_members;
    std::list<StatementNode*> protected_members;
    std::list<StatementNode*> private_members;
};

struct DefineStatementNode : public StatementNode {
    std::string type;
    std::string name;
    ExpressionNode* value;
};

struct BlockStatementNode : public StatementNode {
    std::map<std::string, VariableFactorNode> variables;
    std::list<StatementNode*> statements;
    std::map<std::string, ClassStatementNode*> classes;
};

struct DetermineStatementNode : public StatementNode {
    std::pair<ExpressionNode*, StatementNode*> if_statement;
    std::list<std::pair<ExpressionNode*, StatementNode*>> else_if_statement;
    StatementNode* else_statement;
};

struct WhileStatementNode : public StatementNode {
    ExpressionNode* expression;
    StatementNode* statement;
};

struct ForStatementNode : public StatementNode {
    bool iterator_mode;
    ExpressionNode* expression[3];
    StatementNode* statement;
};

class File {
private:
    unsigned int segment;
    TokenGroup token_group;
    BlockStatementNode* parent = new BlockStatementNode();
    Token peek(int offset = 0);
    DefineStatementNode* isDefineStatementNode();
public:
    std::string file_name;
    explicit File(const std::string &file_name);
};

class Parser {
private:
    std::map<std::string, File*> files;
public:
    Parser(std::string file_name);
};

#endif